import React, { useState, useMemo, useCallback } from 'react';

// 在前端开发的过程中，我们需要缓存一些内容，避免在渲染过程中因大量不必要的耗时计算而导致性能问题。为此react
// 提供了一些方法可以帮助我们去实现数据的缓存。useMemo，useCallback
export default function Demo() {
    let [x, setX] = useState(10);
    let [y, setY] = useState(20);
    // 视图中需要呈现的内容，是经过复杂且大量消耗性能的计算得来的。
    // const computed = () => {
    //     // 复杂计算
    //     return x
    // }

    const cacheVal = useMemo(() => {
        console.log('计算中');
        return x
    }, [x]);

    return (
        <div>
            {/* <span>{computed()}</span> */}
            <span>{cacheVal}</span>
            <span>{y}</span>
            <button onClick={() => setX(x+1)}>修改x</button>
            <button onClick={() => setY(y+1)}>修改y</button>
        </div>
    )
}

// useCallback 用于得到一个固定引用值的函数。通常用它进行性能优化
// useCallback 主要用于父子组件嵌套，父组件会基于属性把方法传递给子组件的情况
function Child1(props) {
    return (
        <div>
            子组件1
            <button onClick={props.handler1}>处理</button>
        </div>
    )
}
function Child2(props) {
    return (
        <div>
            子组件2
            <button onClick={props.handler2}>处理</button>
        </div>
    )
}
export default function Demo() {
    let [num, setNum] = useState(0);

    // 第一次执行，创建函数
    const handler1 = () => {
        console.log(11111);
    }
    // const handler2 = () => {
    //     console.log(22222);
    // }
    // useCallback 可以保证父组件（函数组件）每次更新，不会创建新的函数堆，而是获取之前创建的函数引用，这样传递给子组件的函数值不会变化。
    // 如果子组件做了优化，例如：PureComponent，则可以避免子组件的无效更新，节约一些性能。
    const handler2 = useCallback(() => {
        console.log(222222);
    }, [])

    return (
        <div>
            <Child1 handler1={handler1}></Child1>
            <Child2 handler2={handler2}></Child2>
            <button onClick={() => setNum(100)}></button>
        </div>
    )
}

// 函数组件如何像PureComponent组件进行传值的比较
// memo函数
// memo函数会对函数组件的属性进行钱比较，两次传递的属性值如果相同，则函数不会更新
const Child2 = memo(function Child2(props) {
    return (
        <div>
            子组件2
            <button onClick={props.handler2}>处理</button>
        </div>
    )
});